// Copyright (c) Microsoft Corporation. All rights reserved.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml.XPath;

using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace Microsoft.TeamFoundation.Migration.Toolkit.Wit
{
    /// <summary>
    /// The enumeration defines what name type will be used with TFS fields.
    /// </summary>
    public enum TfsFieldForm
    {
        Friendly,
        Reference,
    };

    /// <summary>
    /// TFS end point.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Tfs")]
    public class TfsMigrationDataSource : IWorkItemTrackingEndpoint
    {
        private string m_server;                            // TF server
        private string m_project;                           // Project
        private string m_filter;                            // Optional filter
        private QueueConfiguration m_writeQueueConfig;      // Write queue configuration
        private TfsAttachmentConfiguration m_fileAttachConfig; //File attachment configuration
        private TfsLinkConfiguration m_linkConfig;          // Links configuration
        private TfsFieldForm m_fieldForm;                   // Field form
        private WorkItemTrackingSession m_session;          // Session info
        private string m_defaultArea;                       // Default area
        private string m_defaultIteration;                  // Default iteration
        private TfsMetadataPolicy m_metadataSync;           // Metadata synchronization policy
        private List<string> m_flatFields;                  // List of flat fields (for testing purposes only!)

        /// <summary>
        /// Server id.
        /// </summary>
        public string Server
        {
            get { return m_server; }
            internal set { m_server = value; }
        }

        /// <summary>
        /// Name of the TFS project.
        /// </summary>
        public string Project
        {
            get { return m_project; }
            internal set { m_project = value; }
        }

        /// <summary>
        /// Optional filter which will be used to obtain work items. If no filter is specified, all
        /// work items from under the project will be returned.
        /// </summary>
        public string Filter
        {
            get { return m_filter; }
            internal set { m_filter = value; }
        }

        /// <summary>
        /// Returns the default area, if any.
        /// </summary>
        public string DefaultArea
        {
            get { return m_defaultArea; }
            internal set { m_defaultArea = value; }
        }

        /// <summary>
        /// Returns the default iteration, if any.
        /// </summary>
        public string DefaultIteration
        {
            get { return m_defaultIteration; }
            internal set { m_defaultIteration = value; }
        }
        
        /// <summary>
        /// File attachment configuration parameters.
        /// </summary>
        public TfsAttachmentConfiguration FileAttachmentConfig { get { return m_fileAttachConfig; } }

        /// <summary>
        /// Linking configuration parameters
        /// </summary>
        public TfsLinkConfiguration LinkConfig { get { return m_linkConfig; } }

        /// <summary>
        /// Returns field type that will be used with the TFS source.
        /// </summary>
        public TfsFieldForm FieldForm { get { return m_fieldForm; } }

        /// <summary>
        /// Returns metadata synchronization policy.
        /// </summary>
        public TfsMetadataPolicy MetadataSynchronizationPolicy { get { return m_metadataSync; } }

        /// <summary>
        /// Gets the list of flat fields.
        /// </summary>
        internal List<string> FlatFields { get { return m_flatFields; } }

        /// <summary>
        /// Initializes object from the XML.
        /// </summary>
        /// <param name="nav">XML navigator positioned to the Tfs section</param>
        /// <param name="session">Current session information</param>
        internal TfsMigrationDataSource(
            XPathNavigator nav,
            WorkItemTrackingSession session)
        {
            m_session = session;
            m_flatFields = new List<string>();

            Debug.Assert(nav.Name == "Tfs", "Invalid XML!");
            m_server = nav.GetAttribute("server", string.Empty);
            m_project = nav.SelectSingleNode("Project").Value;

            // Filter is optional
            XPathNavigator filter = nav.SelectSingleNode("Filter");
            if (filter != null)
            {
                m_filter = filter.Value;
            }
            else
            {
                m_filter = string.Empty;
            }

            // Default area is optional
            XPathNavigator def = nav.SelectSingleNode("DefaultArea");
            m_defaultArea = def == null ? string.Empty : def.Value;

            // Default iteration is optional
            def = nav.SelectSingleNode("DefaultIteration");
            m_defaultIteration = def == null ? string.Empty : def.Value;

            m_writeQueueConfig = QueueConfiguration.Create(
                QueueType.Write, 
                nav.SelectSingleNode("WriteQueue"));

            m_fileAttachConfig = TfsAttachmentConfiguration.Create(
                nav.SelectSingleNode("FileAttachments"));

            m_linkConfig = TfsLinkConfiguration.Create(
                nav.SelectSingleNode("Links"));

            m_metadataSync = new TfsMetadataPolicy(nav.SelectSingleNode("MetadataSynchronization"));

            string fieldForm = nav.GetAttribute("fieldForm", string.Empty);

            if (fieldForm == "Friendly")
            {
                m_fieldForm = TfsFieldForm.Friendly;
            }
            else
            {
                Debug.Assert(fieldForm == "Reference", "Unsupported field type!");
                m_fieldForm = TfsFieldForm.Reference;
            }
        }

        #region IWorkItemTrackingEndpoint Members

        /// <summary>
        /// Provides a unique, user-friendly name for this endpoint
        /// </summary>
        public string FullName
        {
            get { return Server + " (" + Project + ")"; }
        }

        /// <summary>
        /// Gets write queue configuration.
        /// </summary>
        public QueueConfiguration WriteQueueConfig
        {
            get { return m_writeQueueConfig; }
            set { m_writeQueueConfig = value; }
        }

        /// <summary>
        /// Returns session the source belongs to.
        /// </summary>
        public WorkItemTrackingSession Session 
        { 
            get { return m_session; } 
            set { m_session = value; } 
        }
                
        #endregion


        #region IMigrationWorkItemStoreFactory Members

        /// <summary>
        /// Creates a TFS work item store.
        /// </summary>
        /// <returns>TFS work item store</returns>
        public IMigrationWorkItemStore CreateWorkItemStore()
        {
            TfsCore core = new TfsCore(
                this,
                m_session.Policies.MissingArea,
                m_session.Policies.MissingIteration);

            return new TfsMigrationWorkItemStore(core);
        }

        #endregion
    }
}
